package com.example.javaee.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.javaee.dao.CourseMapper;
import com.example.javaee.dao.UserCourseMapper;
import com.example.javaee.domain.UserCourse;
import com.example.javaee.domain.Course;
import com.example.javaee.exception.CourseAdminException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class CourseService
{
    @Autowired
    CourseMapper courseMapper;

    @Autowired
    UserCourseMapper userCourseMapper;

    Logger logger = LoggerFactory.getLogger(getClass());

    public IPage<Course> findCourse(Map<String, Object> condition, Integer pageNum, Integer pageSize, Long isAllCourse)
    {
        LambdaQueryWrapper<Course> lqw = new LambdaQueryWrapper<>();
        if(isAllCourse == null || isAllCourse == 0)
        {
            lqw.select(Course::getCourseNumber, Course::getCourseName, Course::getCollege, Course::getMajor, Course::getGrade, Course::getCredit, Course::getClassification);
        }
        lqw.eq(condition.containsKey("courseNumber"), Course::getCourseNumber, condition.get("courseNumber"));
        lqw.like(condition.containsKey("courseName"), Course::getCourseName, condition.get("courseName"));
        lqw.like(condition.containsKey("major"), Course::getMajor, condition.get("major"));
        lqw.like(condition.containsKey("college"), Course::getMajor, condition.get("college"));
        lqw.eq(condition.containsKey("grade"), Course::getGrade, condition.get("grade"));
        lqw.eq(condition.containsKey("classification"), Course::getClassification, condition.get("classification"));
        if(condition.containsKey("credit"))                 // 浮点数比较需要特殊处理
        {
            Float credit = (Float) condition.get("credit");
            if (credit == 0)
            {
                lqw.lt(Course::getCredit, credit + 0.0001);
            }
            else
            {
                lqw.gt(Course::getCredit, credit - 0.0001).lt(Course::getCredit, credit + 0.0001);
            }
        }
        Page<Course> page = new Page<>(pageNum, pageSize);
        courseMapper.selectPage(page, lqw);
        return page;
    }

    public List<Course> getCourseList(String college,String major,long grade){
        List<Course> courseList = new ArrayList<>();
        QueryWrapper<Course> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(Course::getCollege,college)
                .eq(Course::getMajor,major)
                .eq(Course::getGrade,grade)
                .groupBy(Course::getCourseNumber);

        courseList = courseMapper.selectList(qw);

        return courseList;
    }
    public List<Course> adminGetCourseList(String courseName) {
        List<Course> courseList = new ArrayList<>();
        QueryWrapper<Course> qw = new QueryWrapper<>();
        qw.lambda().eq(Course::getCourseName,courseName);
        courseList = courseMapper.selectList(qw);

        return courseList;
    }
    public List<Course> getCourseDetails(Long courseNumber)
    {
        List<Course> list = new ArrayList<>();
        LambdaQueryWrapper<Course> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Course::getCourseNumber, courseNumber);
        list = courseMapper.selectList(lqw);
        return list;
    }

    //根据用户名返回所选课程的完整信息
    public List<Course> getSelectedCourses(Long userId)
    {
        List<Course> result = new ArrayList<>();
        result = userCourseMapper.getCoursesByUserId(userId);
        return result;
    }

    public void selectCourse(Long userId, Long id) throws CourseAdminException
    {
        // 获取所有该用户选课信息
        List<Course> selectedCourses = getSelectedCourses(userId);
        Course selected = courseMapper.selectById(id);

        logger.info("selected.courseNumber=" + selected.getCourseNumber());
        // 判断是否已经选过该门课程
        for(Course n : selectedCourses)
        {
            logger.info("selectedCourses.courseNumber=" + n.getCourseNumber());
            if(n.getCourseNumber().longValue() == selected.getCourseNumber().longValue())
            {
                throw new CourseAdminException(
                        "已经选过课程'(" + selected.getCourseNumber()+ ")" + selected.getCourseName() + "'.同一个课头号下只能选择一门课程！");
            }
        }
        // 用于判断选课时间是否重合
        boolean[][] schedule = new boolean[7][15];
        selectedCourses.add(selected);
        for(Course course : selectedCourses)
        {
            String times = course.getTime();
            String[] splited = times.split(",");
            for(String time : splited)
            {
                String[] lim = time.split("-");
                int day = Integer.parseInt(lim[0]);
                int st = Integer.parseInt(lim[1]);
                int ed = Integer.parseInt(lim[2]);
                for(int i = st; i <= ed; i++)
                {
                    if(schedule[day][i])
                    {
                        throw new CourseAdminException(
                                "目标课程和已选课程在时间上有冲突！");
                    }
                    schedule[day][i] = true;
                }
            }
        }
        UserCourse userToCourse = new UserCourse(userId, id);
        userCourseMapper.insert(userToCourse);
    }

    public void undoSelection(Long userId, Long id) throws CourseAdminException
    {
        try
        {
            LambdaQueryWrapper<UserCourse> lqw = new LambdaQueryWrapper<>();
            lqw.eq(UserCourse::getUserId, userId);
            lqw.eq(UserCourse::getCourseId, id);
            userCourseMapper.delete(lqw);
        }
        catch (Exception e)
        {
            throw new CourseAdminException("撤销选课失败！");
        }
    }

    /**
     * 课程增删改操作
     */
    public void addCourse(Course course) throws CourseAdminException
    {
        courseMapper.insert(course);
    }

    public void deleteCourse(Long id) throws CourseAdminException
    {
        try
        {
            if(courseMapper.selectById(id) == null)
            {
                throw new CourseAdminException(
                        "课程不存在!");
            }
            courseMapper.deleteById(id);
        }
        catch (Exception e)
        {
            throw new CourseAdminException("课程删除失败！");
        }
    }

    @Transactional
    public void updateCourse(Long id, Course course) throws CourseAdminException
    {
        try
        {
            if(courseMapper.selectById(id) == null)
            {
                throw new CourseAdminException(
                        "课程不存在!");
            }
            courseMapper.deleteById(id);
            course.setId(id);
            courseMapper.insert(course);
        }
        catch (Exception e)
        {
            throw new CourseAdminException("课程更新失败！");
        }
    }

    public void deleteAll()
    {
        courseMapper.delete(new QueryWrapper<>());
    }

    public String getCourseName(Long courseNumber)
    {
        List<Course> courses = getCourseDetails(courseNumber);
        return courses.get(0).getCourseName();
    }
}
